home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 22
/
Cream of the Crop 22.iso
/
program
/
javnl010.zip
/
javnl010.txt
< prev
Wrap
Text File
|
1996-10-03
|
16KB
|
447 lines
Issue #010
October, 1996
Contents:
The Finally Clause and Method Exiting
Comparing C/C++ and Java Part 10 - Labelled Break and Continue
Performance - Garbage Collection and Setting to Null
Newsletter Writing
Introduction to Applet Programming Part 6 - Text Fields
REVIEWERS NEEDED
I am looking for a couple of additional people to help review this
newsletter. If you are a reviewer, you receive the issue a few days
early, and send me your comments. The present set of reviewers have
done much to improve the quality of the newsletter. If you have Java
experience and are interested in this, please send me a note
(glenm@glenmccl.com).
THE FINALLY CLAUSE AND METHOD EXITING
Java has no "goto" statement, though this identifier is reserved in
the language. There are several ways in which goto is used in C and
C++, and it's interesting to consider the Java alternatives to such
usage. In this section we will discuss one alternative, and in the
next section another.
One way that goto is used is to jump to the end of a function body,
where cleanup can be done. For example, suppose that we are
manipulating calendar dates, and have a function where we want a year
in the range 1900-99 and evenly divisible by 4. In C, we might have:
void f(int d)
{
if (d < 1900)
goto err;
if (d > 1999)
goto err;
if (d % 4)
goto err;
/* do stuff with date ... */
return;
err:
fprintf(stderr, "invalid date %d\n", d);
}
In Java, we can achieve a similar end without goto, by using a form of
the try-catch-finally statement used in exception handling:
public class test {
public static void f(int d)
{
boolean err = true;
try {
if (d < 1900)
return;
if (d > 1999)
return;
if (d % 4 != 0)
return;
err = false;
// do stuff with date ...
}
finally {
if (err)
System.err.println("invalid date "
+ d);
}
}
public static void main(String args[])
{
f(1852);
f(1976);
f(1989);
}
}
The code within the try block is "tried", that is, executed. After
the execution of this code, the finally block is executed -- no matter
what happens in the try block. In the example above, we exit the
method (return) for various error conditions, but when the method is
exited, the finally block is executed. In this way, we can execute a
series of Java statements, and guarantee that no matter what happens
in those statements, some other processing will follow.
Whether this programming style is "good" is a matter of opinion.
Saying "return" with the idea that some cleanup will be done by a
finally block could be viewed as a little sneaky or confusing, or
alternatively this might turn out to be a common Java idiom in a few
months or years. At the least, you might put in a comment like:
if (condition)
return; // proceed to cleanup phase of method
If an exception is thrown in a try block, and there is a local catch
block to handle it, the catch block is executed, and then the finally
block. If there is not a local catch block, the finally block is
executed, and then the exception is propagated to the nearest catch
block that can handle the exception (that is, the stack is unwound, as
in other exception processing).
We will say more about Java exception handling at some future point.
COMPARING C/C++ AND JAVA PART 10 - LABELLED BREAK AND CONTINUE
In C and C++, the break and continue statements are used to break out
of and continue with the next iteration of loops, for example while or
for loops. break is also used in switch statements.
Such breaking and continuing apply only to the enclosing loop.
Sometimes you'd like more flexibility, for example the ability to
break out two levels. In C, you might say:
for (i = 1; i <= 10; i++) {
for (j = 1; j <= 10; j++) {
if (some condition)
goto done;
/* other processing in loop */
}
}
done:
/* other processing */
This effect could also be achieved by breaking out of the inner loop,
and then testing some program state variable, and then breaking out of
the outer loop.
In Java, there's a simpler approach to solving this problem. The
above could be written as:
outer_block:
for (i = 1; i <= 10; i++) {
for (j = 1; j <= 10; j++) {
if (some condition)
break outer_block;
// other processing in loop
}
}
// control comes here when break is executed
The break statement has a label. When the statement is executed,
control transfers out of the enclosed labelled statement. Control is
NOT transferred to the label, but to a point past the end of the
labelled statement. A labelled continue statement works in a similar
way; control is transferred to the end of a labelled loop.
Note that with both break and continue, any finally block will be
executed before the labelled statement is exited or the next iteration
of a loop takes place. For example:
loop:
while (some condition) {
try {
if (some condition)
continue loop;
// other processing
}
finally {
// some processing
}
}
The labelled continue statement will cause the finally block to be
executed before going to the bottom of the while loop in preparation
for the next iteration of the loop.
PERFORMANCE - GARBAGE COLLECTION AND SETTING TO NULL
In issue #001 we talked about Java garbage collection, where the
runtime system automatically reclaims dynamic storage that is no longer
in use. For example:
public class test {
public void f()
{
char buf[] = new char[1024];
// stuff that uses buf
}
}
When method f() exits, the space that buf uses is garbage, because
only a local variable in an invalid stack frame references it. The
runtime system may eventually reclaim the storage.
Garbage collection is automatic. But sometimes there are ways to help
it out. Consider a case where you are managing a stack of Object
references:
public class Stack {
private static final int MAXLEN = 10;
private Object stk[] = new Object[MAXLEN];
private int stkp = -1;
// add in logic for error checking, stack growing, etc. ...
public void push(Object p)
{
stk[++stkp] = p;
}
public Object pop()
{
return stk[stkp--];
}
}
Consider a case where the stack has two elements on it, and you pop
one of them. At this point stk[0] will have a valid element in it,
and stk[1] will have the element just popped. That is, stk[1] will
have a reference to an Object, which could be a reference to anything,
including a large data structure of many thousands of bytes. In such
a case, this data structure cannot be garbage collected, even though
it may no longer be in use.
To remedy this problem, we can rewrite pop() like so:
public Object pop()
{
Object p = stk[stkp];
stk[stkp--] = null;
return p;
}
We haven't nullified the Object itself, just a no longer valid
reference to it. The Stack object itself may have a long lifetime,
and rewriting the pop() method in this way helps ensure that garbage
collection can be done in a timely way.
NEWSLETTER WRITING
Would your company find it valuable to have a customized newsletter on
C++ or Java or related topics, similar to this newsletter that you're
reading right now? If so, please contact me (glenm@glenmccl.com) for
further information. Custom newsletters can consist of technical
material furnished from outside, internal material with outside
editting, or a combination of the two.
INTRODUCTION TO APPLET PROGRAMMING PART 6 - TEXT FIELDS
In the previous issue we showed how to use low-level character input
within an applet. In this issue we'll discuss higher-level input
using TextFields. Consider the following example, an applet that
gathers name and address from a user and writes the data to a local
file:
import java.applet.*;
import java.awt.*;
import java.io.*;
public class text4 extends Applet {
TextField tf1; // text fields for address
TextField tf2;
TextField tf3;
Button db; // Done button
Label lb; // Label used as message
Color bg = new Color(0xffffff); // background/foreground clrs
Color fg = new Color(0x000000);
public void init()
{
// set colors
setForeground(fg);
setBackground(bg);
// create text fields
tf1 = new TextField(35);
tf2 = new TextField(35);
tf3 = new TextField(35);
// create button and label
db = new Button("Done");
lb = new Label();
// arrange items in window
setLayout(new GridLayout(4, 2, 10, 10));
add(new Label("Name:"));
add(tf1);
add(new Label("Address #1:"));
add(tf2);
add(new Label("Address #2:"));
add(tf3);
add(db);
add(lb);
}
private boolean write()
{
// check input fields
if (tf1.getText() == null ||
tf1.getText().length() == 0)
return false;
if (tf2.getText() == null ||
tf2.getText().length() == 0)
return false;
if (tf3.getText() == null ||
tf3.getText().length() == 0)
return false;
// write out name and address to end of file
try {
RandomAccessFile raf = new
RandomAccessFile("datafile", "rw");
raf.seek(raf.length());
raf.writeBytes(tf1.getText());
raf.writeByte('\n');
raf.writeBytes(tf2.getText());
raf.writeByte('\n');
raf.writeBytes(tf3.getText());
raf.writeByte('\n');
raf.writeByte('\n');
raf.close();
}
catch (Throwable e) {
}
return true;
}
public boolean action(Event e, Object o)
{
// Done button selected
if (e.target == db) {
if (write())
lb.setText("Written ...");
else
lb.setText("Invalid field value");
return true;
}
else {
return false;
}
}
}
This applet uses the following HTML code to drive it:
<html>
<body bgcolor="#ffffff" text="#000000" link="#ff0000" vlink="#000000">
<head>
<title>Interface to Text Applet</title>
</head>
<body>
Please enter your name and address then select Done.
<br>
<br>
<applet code="text4.class" width=350 height=125></applet>
</body>
</html>
In this example, we use the init() method of the applet to set the
background and foreground colors, and then we create the individual
items of the window. We use a layout manager for this purpose. A
layout manager is a mechanism for arranging items in a window, or more
precisely, Component objects in a Container. Applet is derived from
Panel which is derived from Container. And an item like TextField is
derived from TextComponent which is derived from Component.
So when we create text fields and buttons and so on, we are creating
objects of classes derived from Component, and using a layout manager
to arrange these objects in a Container object.
After we've set up the window items, we can then add some logic within
the action() method to check whether the user selected the Done
button, and if so, then we interrogate the text fields using getText()
and extract the input data. Finally, we write this data to a file.
We append to the end of the file by obtaining its length and
positioning at the end of file.
ACKNOWLEDGEMENTS
Thanks to Thierry Ciot, Irv Kanode, and Mike Paluka for help with
proofreading.
SUBSCRIPTION INFORMATION / BACK ISSUES
To subscribe to the newsletter, send mail to majordomo@world.std.com
with this line as its message body:
subscribe java_letter
Back issues are available via FTP from:
rmi.net /pub2/glenm/javalett
or on the Web at:
http://rmi.net/~glenm
There is also a C++ newsletter. To subscribe to it, say:
subscribe c_plus_plus
using the same majordomo@world.std.com address.
-------------------------
Copyright (c) 1996 Glen McCluskey. All Rights Reserved.
This newsletter may be further distributed provided that it is copied
in its entirety, including the newsletter number at the top and the
copyright and contact information at the bottom.
Glen McCluskey & Associates
Professional Computer Consulting
Internet: glenm@glenmccl.com
Phone: (800) 722-1613 or (970) 490-2462
Fax: (970) 490-2463
FTP: rmi.net /pub2/glenm/javalett (for back issues)
Web: http://rmi.net/~glenm